home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / cug236.zip / BAWK.C < prev    next >
Text File  |  1980-01-02  |  12KB  |  616 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        BAWK Text Pattern/Action Tool (Brod86);
  4.     DATE:        05/17/1987;
  5.     DESCRIPTION:    "BAWK scans text files for regular expression patterns
  6.             and executes a user-defined action (C code fragment)
  7.             for each specified pattern found.  Descended from the
  8.             DECUS version of the same program.";
  9.     VERSION:    1.1;
  10.     KEYWORDS:    Text Filter;
  11.     FILENAME:    BAWK.C;
  12.     SEE-ALSO:    BAWK.H, BAWK.DOC, BAWKACT.C, BAWKDO.C, BAWKPAT.C,
  13.             BAWKSYM.C;
  14.     COMPILERS:    vanilla;
  15.     AUTHORS:    W. C. Colley III, B. Brodt;
  16.     WARNINGS:    "Program runs out of memory under CP/M Eco-C and dies
  17.             without a trace.  Aztec C II is OK.  Won't compile
  18.             yet under ECO-C88 -- module bawkdo.c gives a strange
  19.             code generator error.  REQUIRES that sizeof(int) ==
  20.             sizeof(char *)!!!!!  Therefore, the MSDOS small model
  21.             is OK, but the MSDOS large model is no good.";
  22. */
  23.  
  24. /*
  25.  * Bawk main program
  26.  */
  27. #define MAIN 1
  28. #include <stdio.h>
  29. #include "bawk.h"
  30.  
  31. /* Functions local to this module.    */
  32.  
  33. void compile(), newfile(), process(), usage();
  34.  
  35. /*
  36.  * Main program
  37.  */
  38. int main( argc, argv )
  39. int argc;
  40. char **argv;
  41. {
  42.     char gotrules, didfile, getstdin;
  43.  
  44.     getstdin =
  45.     didfile =
  46.     gotrules = 0;
  47.  
  48.     /*
  49.      * Initialize global variables:
  50.      */
  51.     Stackptr = Stackbtm - 1;
  52.     Stacktop = Stackbtm + MAXSTACKSZ;
  53.     Nextvar = Vartab;
  54.  
  55.     strcpy( Fldsep, " \t" );
  56.     strcpy( Rcrdsep, "\n" );
  57.  
  58.     /*
  59.      * Parse command line
  60.      */
  61.     while ( --argc )
  62.     {
  63.         if ( **(++argv) == '-' )
  64.         {
  65.             /*
  66.              * Process dash options.
  67.              */
  68.             switch (*++*argv)
  69.             {
  70. #ifdef DEBUG
  71.             case 'D':
  72.             case 'd':
  73.                 ++Debug;
  74.                 break;
  75. #endif
  76.             case 0:
  77.                 ++getstdin;
  78.                 --argv;
  79.                 goto dosomething;
  80.                 break;
  81.             default: usage();
  82.             }
  83.         }
  84.         else
  85.         {
  86. dosomething:
  87.             if ( gotrules )
  88.             {
  89.                 /*
  90.                  * Already read rules file - assume this is
  91.                  * is a text file for processing.
  92.                  */
  93.                 if ( ++didfile == 1 && Beginact )
  94.                     doaction( Beginact );
  95.                 if ( getstdin )
  96.                 {
  97.                     --getstdin;
  98.                     newfile( 0 );
  99.                 }
  100.                 else
  101.                     newfile( *argv );
  102.                 process();
  103.             }
  104.             else
  105.             {
  106.                 /*
  107.                  * First file name argument on command line
  108.                  * is assumed to be a rules file - attempt to
  109.                  * compile it.
  110.                  */
  111.                 if ( getstdin )
  112.                 {
  113.                     --getstdin;
  114.                     newfile( 0 );
  115.                 }
  116.                 else
  117.                     newfile( *argv );
  118.                 compile();
  119.                 gotrules = 1;
  120.             }
  121.         }
  122.     }
  123.     if ( !gotrules )
  124.         usage();
  125.  
  126.     if ( ! didfile )
  127.     {
  128.         /*
  129.          * Didn't process any files yet - process stdin.
  130.          */
  131.         newfile( 0 );
  132.         if ( Beginact )
  133.             doaction( Beginact );
  134.         process();
  135.     }
  136.     if ( Endact )
  137.         doaction( Endact );
  138.     return 0;
  139. }
  140.  
  141. /*
  142.  * Regular expression/action file compilation routines.
  143.  */
  144. void compile()
  145. {
  146.     /*
  147.      * Compile regular expressions and C actions into Rules struct,
  148.      * reading from current input file "Fileptr".
  149.      */
  150.     int c, len;
  151.  
  152. #ifdef DEBUG
  153.     if ( Debug )
  154.         error( "compiling...", 0 );
  155. #endif
  156.  
  157.     while ( (c = getcharacter()) != -1 )
  158.     {
  159.         if ( c==' ' || c=='\t' || c=='\n' )
  160.             /* swallow whitespace */
  161.             ;
  162.         else if ( c=='#' )
  163.         {
  164.             /*
  165.              * Swallow comments
  166.              */
  167.             while ( (c=getcharacter()) != -1 && c!='\n' )
  168.                 ;
  169.         }
  170.         else if ( c=='{' )
  171.         {
  172. #ifdef DEBUG
  173.             if ( Debug )
  174.                 error( "action", 0 );
  175. #endif
  176.             /*
  177.              * Compile (tokenize) the action string into our
  178.              * global work buffer, then allocate some memory
  179.              * for it and copy it over.
  180.              */
  181.             ungetcharacter( '{' );
  182.             len = act_compile( Workbuf );
  183.  
  184.             if ( Rulep && Rulep->action )
  185.             {
  186.                 Rulep->nextrule =
  187.                     (RULE *)getmem(sizeof(RULE));
  188.                 Rulep = Rulep->nextrule;
  189.                 fillmem( Rulep, sizeof(RULE), 0 );
  190.             }
  191.             if ( !Rulep )
  192.             {
  193.                 /*
  194.                  * This is the first action encountered.
  195.                  * Allocate the first Rules structure and
  196.                  * initialize it
  197.                  */
  198.                 Rules = Rulep =
  199.                     (RULE *)getmem(sizeof(RULE));
  200.                 fillmem( Rulep, sizeof(RULE), 0 );
  201.             }
  202.             Rulep->action = getmem( len );
  203.             movemem( Workbuf, Rulep->action, len );
  204.         }
  205.         else if ( c==',' )
  206.         {
  207. #ifdef DEBUG
  208.             if ( Debug )
  209.                 error( "stop pattern", 0 );
  210. #endif
  211.             /*
  212.              * It's (hopefully) the second part of a two-part
  213.              * pattern string.  Swallow the comma and start
  214.              * compiling an action string.
  215.              */
  216.             if ( !Rulep || !Rulep->pattern.start )
  217.                 error( "stop pattern without a start",
  218.                     RE_ERROR );
  219.             if ( Rulep->pattern.stop )
  220.                 error( "already have a stop pattern",
  221.                     RE_ERROR );
  222.             len = pat_compile( Workbuf );
  223.             Rulep->pattern.stop = getmem( len );
  224.             movemem( Workbuf, Rulep->pattern.stop, len );
  225.         }
  226.         else
  227.         {
  228.             /*
  229.              * Assume it's a regular expression pattern
  230.              */
  231. #ifdef DEBUG
  232.             if ( Debug )
  233.                 error( "start pattern", 0 );
  234. #endif
  235.  
  236.             ungetcharacter( c );
  237.             len = pat_compile( Workbuf );
  238.  
  239.             if ( *Workbuf == T_BEGIN )
  240.             {
  241.                 /*
  242.                  * Saw a "BEGIN" keyword - compile following
  243.                  * action into special "Beginact" buffer.
  244.                  */
  245.                 len = act_compile( Workbuf );
  246.                 Beginact = getmem( len );
  247.                 movemem( Workbuf, Beginact, len );
  248.                 continue;
  249.             }
  250.             if ( *Workbuf == T_END )
  251.             {
  252.                 /*
  253.                  * Saw an "END" keyword - compile following
  254.                  * action into special "Endact" buffer.
  255.                  */
  256.                 len = act_compile( Workbuf );
  257.                 Endact = getmem( len );
  258.                 movemem( Workbuf, Endact, len );
  259.                 continue;
  260.             }
  261.             if ( Rulep )
  262.             {
  263.                 /*
  264.                  * Already saw a pattern/action - link in
  265.                  * another Rules structure.
  266.                  */
  267.                 Rulep->nextrule =
  268.                     (RULE *)getmem(sizeof(RULE));
  269.                 Rulep = Rulep->nextrule;
  270.                 fillmem( Rulep, sizeof(RULE), 0 );
  271.             }
  272.             if ( !Rulep )
  273.             {
  274.                 /*
  275.                  * This is the first pattern encountered.
  276.                  * Allocate the first Rules structure and
  277.                  * initialize it
  278.                  */
  279.                 Rules = Rulep =
  280.                     (RULE *)getmem(sizeof(RULE));
  281.                 fillmem( Rulep, sizeof(RULE), 0 );
  282.             }
  283.             if ( Rulep->pattern.start )
  284.                 error( "already have a start pattern",
  285.                     RE_ERROR );
  286.  
  287.             Rulep->pattern.start = getmem( len );
  288.             movemem( Workbuf, Rulep->pattern.start, len );
  289.         }
  290.     }
  291.     endfile();
  292. }
  293.  
  294. /*
  295.  * Text file main processing loop.
  296.  */
  297. void process()
  298. {
  299.     /*
  300.      * Read a line at a time from current input file at "Fileptr",
  301.      * then apply each rule in the Rules chain to the input line.
  302.      */
  303.     int i;
  304.  
  305. #ifdef DEBUG
  306.     if ( Debug )
  307.         error( "processing...", 0 );
  308. #endif
  309.  
  310.     Recordcount = 0;
  311.  
  312.     while ( getline() )
  313.     {
  314.         /*
  315.          * Parse the input line.
  316.          */
  317.         Fieldcount = parse( Linebuf, Fields, Fldsep );
  318. #ifdef DEBUG
  319.         if ( Debug>1 )
  320.         {
  321.             printf( "parsed %d words:\n", Fieldcount );
  322.             for(i=0; i<Fieldcount; ++i )
  323.                 printf( "<%s>\n", Fields[i] );
  324.         }
  325. #endif
  326.  
  327.         Rulep = Rules;
  328.         do
  329.         {
  330.             if ( ! Rulep->pattern.start )
  331.             {
  332.                 /*
  333.                  * No pattern given - perform action on
  334.                  * every input line.
  335.                  */
  336.                 doaction( Rulep->action );
  337.             }
  338.             else if ( Rulep->pattern.startseen )
  339.             {
  340.                 /*
  341.                  * Start pattern already found - perform
  342.                  * action then check if line matches
  343.                  * stop pattern.
  344.                  */
  345.                 doaction( Rulep->action );
  346.                 if ( dopattern( Rulep->pattern.stop ) )
  347.                     Rulep->pattern.startseen = 0;
  348.             }
  349.             else if ( dopattern( Rulep->pattern.start ) )
  350.             {
  351.                 /*
  352.                  * Matched start pattern - perform action.
  353.                  * If a stop pattern was given, set "start
  354.                  * pattern seen" flag and process every input
  355.                  * line until stop pattern found.
  356.                  */
  357.                 doaction( Rulep->action );
  358.                 if ( Rulep->pattern.stop )
  359.                     Rulep->pattern.startseen = 1;
  360.             }
  361.         }
  362.         while ( Rulep = Rulep->nextrule );
  363.  
  364.         /*
  365.          * Release memory allocated by parse().
  366.          */
  367.         while ( Fieldcount )
  368.             free( Fields[ --Fieldcount ] );
  369.     }
  370. }
  371.  
  372. /*
  373.  * Miscellaneous functions
  374.  */
  375. int parse( str, wrdlst, delim )
  376. char *str;
  377. char *wrdlst[];
  378. char *delim;
  379. {
  380.     /*
  381.      * Parse the string of words in "str" into the word list at "wrdlst".
  382.      * A "word" is a sequence of characters delimited by one or more
  383.      * of the characters found in the string "delim".
  384.      * Returns the number of words parsed.
  385.      * CAUTION: the memory for the words in "wrdlst" is allocated
  386.      * by malloc() and should eventually be returned by fr